package com.jade.modules.config.impl;

import java.util.List;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import com.jade.framework.base.criterion.Criteria;
import com.jade.framework.base.criterion.Restrictions;
import com.jade.framework.base.criterion.sql.SqlUtils;
import com.jade.framework.base.util.PagingList;
import com.jade.modules.config.ConfigDao;
import com.jade.modules.config.ConfigEntity;
import com.jade.modules.config.ConfigException;
import com.jade.modules.config.ConfigGroupEntity;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;

/**
 * 基于JPA方式实现的配置对象访问接口。
 *
 * @author sky
 * @version 1.0 14-11-24 上午8:45
 */
@Named ("module_configDao")
public class JpaConfigDao
        implements ConfigDao
{
    protected static final String SQL_CONFIG = "SELECT entity FROM com.jade.modules.config.ConfigEntity entity";
    protected static final String SQL_GROUP = "SELECT group FROM ConfigGroupEntity group";
    @PersistenceContext (unitName = "default")
    protected EntityManager entityManager;

    @Cacheable (value = "module.config.l", key = "#ownerType + '_' + #ownerId + '_' + #group + '[%GRP%]' + 'list'")
    public List<ConfigEntity> listEntity(String ownerType, String ownerId, String group)
    {
        String sql = SQL_CONFIG + " WHERE ownerType=:ownerType AND ownerId=:ownerId AND group=:group AND status=:status ORDER BY orderCode DESC";
        Query query = entityManager.createQuery(sql);
        query.setParameter("ownerType", ownerType);
        query.setParameter("ownerId", ownerId);
        query.setParameter("group", group);
        query.setParameter("status", ConfigEntity.STATUS_ACTIVE);
        return query.getResultList();
    }

    @Cacheable (value = "module.config.q", key = "#ownerType + '_' + #ownerId + '_' + '[%GRP%]' + #criteria")
    public PagingList<ConfigEntity> queryEntity(String ownerType, String ownerId, Criteria criteria)
    {
        criteria.add(Restrictions.eq("entity","ownerType", ownerType));
        criteria.add(Restrictions.eq("entity","ownerId", ownerId));
        return SqlUtils.sqlQuery(SQL_CONFIG, entityManager, criteria);
    }

    @Cacheable (value = "module.config.g", key = "#id")
    public ConfigEntity getEntity(long id)
    {
        return entityManager.find(ConfigEntity.class, id);
    }

    @Cacheable (value = "module.config.g2", key = "#ownerType + '_' + #ownerId + '_' + #group + '_' + #key")
    public ConfigEntity getEntity(String ownerType, String ownerId, String group, String key)
    {
        String sql = SQL_CONFIG + " WHERE ownerType=:ot AND ownerId=:oid AND group=:grp AND key=:key";
        Query query = entityManager.createQuery(sql);
        query.setParameter("ot", ownerType);
        query.setParameter("oid", ownerId);
        query.setParameter("grp", group);
        query.setParameter("key", key);
        return SqlUtils.getSingleResult(query);
    }

    @Caching (evict = {@CacheEvict (value = "module.config.g", key = "#entity.id"),
            @CacheEvict (value = "module.config.g2",
                    key = "#entity.ownerType + '_' + #entity.ownerId + '_' + #entity.group + '_' + #entity.key"),
            @CacheEvict (value = "module.config.q", key = "#entity.ownerType + '_' + #entity.ownerId + '[%GRP%]'"),
            @CacheEvict (value = "module.config.l",
                    key = "#entity.ownerType + '_' + #entity.ownerId + '_' + #entity.group + '[%GRP%]'")})
    public void addEntity(ConfigEntity entity)
            throws ConfigException
    {
        entityManager.persist(entity);
    }

    @Caching (evict = {@CacheEvict (value = "module.config.g", key = "#entity.id"),
            @CacheEvict (value = "module.config.g2",
                    key = "#entity.ownerType + '_' + #entity.ownerId + '_' + #entity.group + '_' + #entity.key"),
            @CacheEvict (value = "module.config.q", key = "#entity.ownerType + '_' + #entity.ownerId + '[%GRP%]'"),
            @CacheEvict (value = "module.config.l",
                    key = "#entity.ownerType + '_' + #entity.ownerId + '_' + #entity.group + '[%GRP%]'")})
    public void updateEntity(ConfigEntity entity)
            throws ConfigException
    {
        entityManager.merge(entity);
    }

    @Caching (evict = {@CacheEvict (value = "module.config.g", key = "#entity.id"),
            @CacheEvict (value = "module.config.g2",
                    key = "#entity.ownerType + '_' + #entity.ownerId + '_' + #entity.group + '_' + #entity.key"),
            @CacheEvict (value = "module.config.q", key = "#entity.ownerType + '_' + #entity.ownerId + '[%GRP%]'"),
            @CacheEvict (value = "module.config.l",
                    key = "#entity.ownerType + '_' + #entity.ownerId + '_' + #entity.group + '[%GRP%]'")})
    public void removeEntity(ConfigEntity entity)
            throws ConfigException
    {
        ConfigEntity e = entityManager.find(ConfigEntity.class, entity.getId());
        if (e != null) {
            entityManager.remove(e);
        }
    }

    @Cacheable (value = "module.config.gl", key = "#ownerType + '_' + #ownerId")
    public List<ConfigGroupEntity> listGroup(String ownerType, String ownerId)
    {
        String sql = "SELECT entity FROM ConfigGroupEntity entity WHERE ownerId=:ownerId and ownerType=:ownerType ORDER BY orderCode DESC";
        Query query = entityManager.createQuery(sql);
        query.setParameter("ownerType", ownerType);
        query.setParameter("ownerId", ownerId);
        return query.getResultList();
    }

    @Cacheable (value = "module.config.gg", key = "#id")
    public ConfigGroupEntity getGroup(long id)
    {
        return entityManager.find(ConfigGroupEntity.class, id);
    }

    @Cacheable (value = "module.config.gg2", key = "#id")
    public ConfigGroupEntity getGroup(String ownerType, String ownerId, String key)
    {
        String sql = "SELECT entity FROM ConfigGroupEntity entity WHERE ownerId=:ownerId and ownerType=:ownerType and key=:key";
        Query query = entityManager.createQuery(sql);
        query.setParameter("ownerType", ownerType);
        query.setParameter("ownerId", ownerId);
        query.setParameter("key", key);
        return SqlUtils.getSingleResult(query);
    }

    public PagingList<ConfigGroupEntity> queryGroup(String ownerType, String ownerId, Criteria criteria)
    {
        criteria.add(Restrictions.eq("ownerType", ownerType));
        criteria.add(Restrictions.eq("ownerId", ownerId));
        return SqlUtils.sqlQuery(SQL_GROUP,entityManager, criteria);
    }

    public void addGroup(ConfigGroupEntity groupEntity)
            throws ConfigException
    {
        entityManager.persist(groupEntity);
    }

    public void updateGroup(ConfigGroupEntity groupEntity)
            throws ConfigException
    {
        entityManager.merge(groupEntity);
    }

    public void removeGroup(ConfigGroupEntity groupEntity)
            throws ConfigException
    {
        entityManager.remove(groupEntity);
    }
}
